home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gold Medal Software 1
/
Gold Medal Software Volume 1 (Gold Medal) (1994).iso
/
graphics
/
tdraw462.arj
/
UNCRUNCH.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1993-09-07
|
8KB
|
161 lines
procedure UNCRUNCH (var Addr1,Addr2; BlkLen:Integer);
(*
This is the routine for displaying crunched TheDraw image files. The
crunched data format is a simple custom protocol for reproducing any image.
The control codes below decimal 32 are reserved for this function.
Characters 32 and above are written directly to the destination address.
The following shows the format of a control code sequence. Please note that
not all functions use the optional bytes <x> or <y>.
Data Structure: <current byte>[<x>[<y>]]
0..15 = New Foreground Color
16..23 = New Background Color
24 = Go down to next line, return to same horizontal position as when
routine was started (akin to a c/r).
25 = Displays <x> number of spaces.
26 = Displays <x> number of <y>. Also used to display ANY characters
below #32. This function is the only way to do this although it
uses three bytes. Otherwise the code would be interpreted as
another command.
27 = Toggles on/off the foreground attribute blink flag.
28..31 = reserved
----------------------------------------------------------------------------
To use this routine, call the procedure with the crunched image data as the
first parameter, the display address as the second parameter, and the length
of the crunched image data as the third parameter.
Assume we have an ImageData file of a 40 character by 10 line block. Also
the following defintions. ie:
{ TheDraw Pascal Crunched Screen Image }
const <- This CONST area is
IMAGEDATA_WIDTH = 40; generated by TheDraw
IMAGEDATA_DEPTH = 10;
IMAGEDATA_LENGTH = 467;
IMAGEDATA : array [1..467] of Char =
(...list of image bytes here...);
type ScreenType = array [0..3999] of Byte;
var ScreenAddr : ScreenType absolute $B800:$0000;
begin
UnCrunch (IMAGEDATA,ScreenAddr[ (34*2) + (5*160) -162],IMAGEDATA_LENGTH);
end;
SCREENADDR is a variable mapped to the same location as the physical video
addresses (via Turbo's absolute addressing). The rather messy array offset
tells UnCrunch where to start displaying the ImageData block. The 34*2
indicates the horizontal position number 34 with the 5*160 indicating line
number 5. This is similar to a Turbo GOTOXY (34,5) statement.
The original horizontal starting offset is remembered by the uncrunch routine.
The offset is restored upon moving down to the next line. This permits a
block to be displayed correctly anywhere on the screen. ie:
┌─ horizontal starting offset
V
+-------------------------------------------------+
| |
| | <- Assume this
| | is the video
| ┌─────────────────────┐ | display.
| │█████████████████████│ |
| │█████████████████████│ |
| │██ ImageData block ██│ |
| │█████████████████████│ |
| │█████████████████████│ |
| │█████████████████████│ |
| └─────────────────────┘ |
| |
| |
| |
+-------------------------------------------------+
The ImageData block could just as well have been display in the upper-left
corner of the screen with:
UNCRUNCH (IMAGEDATA,ScreenAddr[ (1*2) + (1*160) -162],IMAGEDATA_LENGTH);
Notice the array address changed to the equivilant of GOTOXY (1,1);
To display the block in the lower-right corner you would use:
UNCRUNCH (IMAGEDATA,ScreenAddr[ (40*2) + (15*160) -162],IMAGEDATA_LENGTH);
In this example, the block is 40 characters wide by 10 lines deep. Thus,
to display such a large block, we must display the block at GOTOXY (40,15);
That's it! The routine was designed for easy use and understanding; however,
for some people the best way is to experiment. Create a program using the
above examples, perhaps with a 40x10 block (or any size). Good luck!
*)
begin
inline (
$1E/ { PUSH DS ;Save data segment.}
$C5/$B6/ADDR1/ { LDS SI,[BP+Addr1] ;Source Address}
$C4/$BE/ADDR2/ { LES DI,[BP+Addr2] ;Destination Addr}
$8B/$8E/BLKLEN/ { MOV CX,[BP+BlkLen] ;Length of block}
$E3/$5B/ { JCXZ Done}
$8B/$D7/ { MOV DX,DI ;Save X coordinate for later.}
$33/$C0/ { XOR AX,AX ;Set Current attributes.}
$FC/ { CLD}
$AC/ {LOOPA: LODSB ;Get next character.}
$3C/$20/ { CMP AL,32 ;If a control character, jump.}
$72/$05/ { JC ForeGround}
$AB/ { STOSW ;Save letter on screen.}
$E2/$F8/ {Next: LOOP LOOPA}
$EB/$4C/ { JMP Short Done}
{ForeGround:}
$3C/$10/ { CMP AL,16 ;If less than 16, then change the}
$73/$07/ { JNC BackGround ;foreground color. Otherwise jump.}
$80/$E4/$F0/ { AND AH,0F0H ;Strip off old foreground.}
$0A/$E0/ { OR AH,AL}
$EB/$F1/ { JMP Next}
{BackGround:}
$3C/$18/ { CMP AL,24 ;If less than 24, then change the}
$74/$13/ { JZ NextLine ;background color. If exactly 24,}
$73/$19/ { JNC FlashBitToggle ;then jump down to next line.}
$2C/$10/ { SUB AL,16 ;Otherwise jump to multiple output}
$02/$C0/ { ADD AL,AL ;routines.}
$02/$C0/ { ADD AL,AL}
$02/$C0/ { ADD AL,AL}
$02/$C0/ { ADD AL,AL}
$80/$E4/$8F/ { AND AH,8FH ;Strip off old background.}
$0A/$E0/ { OR AH,AL}
$EB/$DA/ { JMP Next}
{NextLine:}
$81/$C2/$A0/$00/ { ADD DX,160 ;If equal to 24,}
$8B/$FA/ { MOV DI,DX ;then jump down to}
$EB/$D2/ { JMP Next ;the next line.}
{FlashBitToggle:}
$3C/$1B/ { CMP AL,27 ;Does user want to toggle the blink}
$72/$07/ { JC MultiOutput ;attribute?}
$75/$CC/ { JNZ Next}
$80/$F4/$80/ { XOR AH,128 ;Done.}
$EB/$C7/ { JMP Next}
{MultiOutput:}
$3C/$19/ { CMP AL,25 ;Set Z flag if multi-space output.}
$8B/$D9/ { MOV BX,CX ;Save main counter.}
$AC/ { LODSB ;Get count of number of times}
$8A/$C8/ { MOV CL,AL ;to display character.}
$B0/$20/ { MOV AL,32}
$74/$02/ { JZ StartOutput ;Jump here if displaying spaces.}
$AC/ { LODSB ;Otherwise get character to use.}
$4B/ { DEC BX ;Adjust main counter.}
{StartOutput:}
$32/$ED/ { XOR CH,CH}
$41/ { INC CX}
$F3/$AB/ { REP STOSW}
$8B/$CB/ { MOV CX,BX}
$49/ { DEC CX ;Adjust main counter.}
$E0/$AA/ { LOOPNZ LOOPA ;Loop if anything else to do...}
$1F); {Done: POP DS ;Restore data segment.}
end; {UNCRUNCH}